package com.beidasoft.web.util.elasticSearch;

import com.beidasoft.web.annotation.ESQuery;
import com.beidasoft.web.util.FzbStringUtil;
import com.beidasoft.web.util.enums.ESOperator;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.*;
import org.springframework.data.elasticsearch.annotations.Field;

import java.util.*;

public class QueryBuilderUtils {

    /**
     * 解析es文档对象中，keyword，text等类型来自动生成查询 QueryBuilder
     * @param document
     * @return
     */
    public static QueryBuilder createQueryBuilder(Object document)  {
        BoolQueryBuilder boolFilterBuilder = QueryBuilders.boolQuery();
        try {
            // 获取文档类所包含的字段信息
            java.lang.reflect.Field[] fields = document.getClass().getDeclaredFields();
            for(java.lang.reflect.Field field : fields) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                // 判断当前字段值是否为空
                Object value = field.get(document);
                if(StringUtils.isNotBlank(FzbStringUtil.getString(value))) {
                    Field fieldAnnotation = field.getAnnotation(Field.class);
                    if(fieldAnnotation != null) {
                        // 当关键字为 keyword 时
                        String key = field.getName();
                        if("Keyword".equals(fieldAnnotation.type().name())) {
                            boolFilterBuilder.must(QueryBuilders.termQuery(key, value));
                        } else if("Text".equals(fieldAnnotation.type().name())) {
                            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key, value);
                            if(StringUtils.isNotBlank(fieldAnnotation.searchAnalyzer())) {
                                matchQueryBuilder.analyzer(fieldAnnotation.searchAnalyzer());
                            }
                            boolFilterBuilder.must(matchQueryBuilder);
                        } else if("Integer".equals(fieldAnnotation.type().name())) {
                            boolFilterBuilder.must(QueryBuilders.termQuery(key, value));
                        }
                    }
                }
            }
            List<java.lang.reflect.Field>  queryFields = ReflectUtils.getClassFieldsByAnnotation(document.getClass(), ESQuery.class);

            // 子查询条件组合
            // 子查询分组
            Set<String> nestedKeyword = new HashSet<>();
            for(int i = 0; i < queryFields.size(); i++) {
                ESQuery queryAnnotation = queryFields.get(i).getAnnotation(ESQuery.class);
                if(ESOperator.nested.equals(queryAnnotation.operator())) {
                    nestedKeyword.add(queryAnnotation.path());
                }
            }
            Iterator<String> it = nestedKeyword.iterator();
            while(it.hasNext()) {
                String keyword = it.next();
                BoolQueryBuilder nestedBoolQueryBuilder = QueryBuilders.boolQuery();
                for(int i = 0; i < queryFields.size(); i++) {
                    ESQuery queryAnnotation = queryFields.get(i).getAnnotation(ESQuery.class);
                    if(ESOperator.nested.equals(queryAnnotation.operator())) {
                        Object value = ReflectUtils.getFieldValue(document, queryFields.get(i));
                        if(StringUtils.isNotBlank(FzbStringUtil.getString(value))) {
                            if(keyword.equals(queryAnnotation.path())) {
                                String[] queryId = FzbStringUtil.getString(value).split(",");
                                if (queryId.length > 0){
                                    nestedBoolQueryBuilder.must(QueryBuilders.termsQuery(queryAnnotation.path() + "." + queryAnnotation.keyword(), Arrays.asList(queryId)));
                                }
                            }
                        }
                    }
                }
                NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(keyword, nestedBoolQueryBuilder, ScoreMode.None);
                nestedQueryBuilder.ignoreUnmapped(true);
                boolFilterBuilder.must(nestedQueryBuilder);
            }
            for(int i = 0; i < queryFields.size(); i++) {
                Object value = ReflectUtils.getFieldValue(document, queryFields.get(i));
                if(StringUtils.isNotBlank(FzbStringUtil.getString(value))) {
                    ESQuery queryAnnotation = queryFields.get(i).getAnnotation(ESQuery.class);
                    // 查询字段
                    String keyword = queryAnnotation.keyword();
                    // 父子模型检索
                    if(!ESOperator.nested.equals(queryAnnotation.operator())) {
                        RangeQueryBuilder rangeBuilder = QueryBuilders.rangeQuery(keyword);
                        if (ESOperator.gt.equals(queryAnnotation.operator())) {
                            rangeBuilder.gt(value);
                        } else if (ESOperator.lt.equals(queryAnnotation.operator())) {
                            rangeBuilder.lt(value);
                        } else if (ESOperator.gte.equals(queryAnnotation.operator())) {
                            rangeBuilder.gte(value);
                        } else if (ESOperator.lte.equals(queryAnnotation.operator())) {
                            rangeBuilder.lte(value);
                        }
                        boolFilterBuilder.must(rangeBuilder);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        ConstantScoreQueryBuilder queryBuilder = QueryBuilders.constantScoreQuery(boolFilterBuilder);
        return queryBuilder;
    }

}
